#ifndef AIRCRAFT_H
#define AIRCRAFT_H

#include <QObject>
#include "fsxdatadefinitions.h"
#include "waypointlist.h"
#include "jsonmarkuphelper.h"

namespace FsxSimConnect {

//! Represents aircraft (plane, heli), basically a data tranfer object.
/*! \author KWB */
class Aircraft : public QObject
{
    Q_OBJECT

private:
    qint64 _lastUpdatedTimestampUtcEpoch; /*!< last updated timestamp */
    FSXAircraftPositionAndSpeedData _positionAndSpeedData; /*!< position and speed data */
    FSXAircraftStringAndMiscData _stringAndMiscData; /*!< string data e.g. title */
    FSXAircraftInstrumentationData _instrumentationData; /*!< instrumentation data, e.g. ias */
    FSXAircraftAvionicsData _avionicsData; /*!< avionics data */
    WaypointList _waypoints; /*!< related waypoints */
    WaypointList _deltaWaypoints; /*!< related delta waypoints */
    SIMCONNECT_OBJECT_ID _id; /*!< unique id */
    bool _isHelicopter; /*<! is this fixed wing or helicopter? */
    bool _validStringData; /*!< correct string data already set? */
    bool _validAvionicsData; /*!< correct avionics data already set? */
    bool _validInstrumentationData; /*!< correct instrumentation data already set? */
    bool _validPositionSpeedData; /*!< correct position / speed data already set? */
    //! Update the current time stamp.
    void updateTimestamp();
    //! Helper method to update waypoints when new data have been set.
    /*! \param int maxWaypoints
        \param qint64 timeFrameMs */
    void setDataPostProcessing(const int maxWaypoints, const qint64 timeFrameMs);
    /// @cond
    Q_PROPERTY(SIMCONNECT_OBJECT_ID id READ getId)
    Q_PROPERTY(FSXAircraftStringAndMiscData stringData READ getStringMiscData WRITE setStringMiscData)
    Q_PROPERTY(FSXAircraftPositionAndSpeedData positionSpeedData READ getPositionSpeedData WRITE setPositionSpeedData)
    Q_PROPERTY(FSXAircraftInstrumentationData instrumentationData READ getInstrumentationData WRITE setInstrumentationData)
    Q_PROPERTY(FSXAircraftAvionicsData AvionicsData READ getAvionicsData WRITE setAvionicsData)
    Q_PROPERTY(qint64 LastUpdated READ getLastUpdatedTimestampUtcEpoch )
    /// @endcond
public:
    //! Constructor.
    /*! \param id Unique object id
        \param isHelicopter
        \param parent Qt parent object */
    Aircraft(SIMCONNECT_OBJECT_ID id = -1, bool isHelicopter = false, QObject *parent = 0); // the id -1 allows to use the constructor as default constructor with Template types T
    //! Copy constructor.
    /*! \param otherAircraft */
    Aircraft(const Aircraft& otherAircraft); // copy constructor
    //! Assigment operator.
    /*! \param otherAircraft */
    Aircraft &operator =(const Aircraft &otherAircraft); // assignment operator
    //! Unique id, 1 = own aircraft */
    /*! \return SIMCONNECT_OBJECT_ID */
    SIMCONNECT_OBJECT_ID getId() const { return Aircraft::_id; }
    //! Is object containing (valid) data, or just empty object?
    /*! \return valid? */
    bool isValid() const { return Aircraft::_id >=0; }
    //! Rotorcraft?
    /*! \return rotorcraft? */
    bool isHelicopter() const { return Aircraft::_isHelicopter; }
    //! Corresponding string / misc. data.
    /*! \return FSXAircraftStringAndMiscData */
    FSXAircraftStringAndMiscData getStringMiscData() const { return Aircraft::_stringAndMiscData; }
    //! Corresponding position and speed data.
    /*! \return FSXAircraftStringData */
    FSXAircraftPositionAndSpeedData getPositionSpeedData() const { return Aircraft::_positionAndSpeedData; }
    //! Corresponding instrumentation data.
    /*! \return FSXAircraftInstrumentationData */
    FSXAircraftInstrumentationData getInstrumentationData() const { return Aircraft::_instrumentationData; }
    //! Corresponding instrumentation data.
    /*! \return FSXAircraftAvionicsData */
    FSXAircraftAvionicsData getAvionicsData() const { return Aircraft::_avionicsData; }
    //! Timestamp when last updated.
    /*! \return timestamp */
    qint64 getLastUpdatedTimestampUtcEpoch() const { return _lastUpdatedTimestampUtcEpoch; }
    //! Related waypoints.
    /*! \return WaypointList */
    WaypointList getWaypoints() const { return _waypoints; }
    //! Related delta waypoints.
    /*! \return WaypointList */
    WaypointList getDeltaWaypoints() const { return _deltaWaypoints; }
    //! Number of related waypoints
    /*! \return waypoint count
        \sa getWaypoints() */
    int waypointsCount() const { return _waypoints.count(); }
    //! Number of related waypoints
    /*! \return waypoint count
        \sa getDeltaWaypoints() */
    int deltaWaypointsCount() const { return _waypoints.count(); }
    //! Timestamp as local time.
    /*! \return hh::mm:ss:zzz */
    QString getLastUpdatedFormattedTimeLocal() const { return FSXHelper::formattedTime(_lastUpdatedTimestampUtcEpoch);}
    //! Timestamp as UTC time.
    /*! \return hh::mm:ss:zzz */
    QString getLastUpdatedFormattedTimeUtc() const { return FSXHelper::formattedTime(_lastUpdatedTimestampUtcEpoch, false);}
    //! Set corresponding string / misc data.
    /*! \param sData */
    void setStringMiscData(const FSXAircraftStringAndMiscData sData);
    //! Set corresponding position / speed data.
    /*! \param psData
        \param maxWaypoints maximum number of waypoints in the list
        \param timeFrameMs time frame of waypoints, oldest waypoint needs to be within this range */
    void setPositionSpeedData(const FSXAircraftPositionAndSpeedData psData, const int maxWaypoints = -1, const qint64 timeFrameMs = -1);
    //! Set corresponding instrumentation data.
    /*! \param iData
        \param maxWaypoints maximum number of waypoints in the list
        \param timeFrameMs time frame of waypoints, oldest waypoint needs to be within this range */
    void setInstrumentationData(const FSXAircraftInstrumentationData iData, const int maxWaypoints = -1, const qint64 timeFrameMs = -1);
    //! Set corresponding avionics data.
    void setAvionicsData(const FSXAircraftAvionicsData aData);
    //! Representing a rotorcraft or fixed wing?
    /*! \param helicopter */
    void setHelicopter(bool helicopter) { Aircraft::_isHelicopter = helicopter; }
    //! Representative title.
    /*! \return title string */
    QString getTitle() const;
    //! Aircraft type and flight number.
    QString getTypeAndFlightnumber() const;
    //! JSON representation of the aircraft and its waypoints.
    /*! \param level indention level
        \param parameter JsonParameter
        \return JSON string */
    QString toJson(const int level, const JsonParameter &parameter) const;
    //! KML waypoint representation of the aircraft's waypoints.
    /*! \param level indention level
        \param parameter KML parameter
        \return kml string */
    QString toKml(const int level, const KmlParameter &parameter) const;
    //! HTML row representing aircraft attributes.
    /*! \param level indention level
        \param withHeader with column headers
        \return html string of a table row */
    QString toHtmlTableRow(const int level, bool withHeader = false) const;
};
}

#endif // AIRCRAFT_H
